﻿using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;

namespace Kz.Telegram.Bot.Infrastructure.Helpers
{
    public class ProcessHelper
    {
        /// <summary>
        /// 获取音频文件采样率
        /// </summary>
        /// <param name="filePath"></param>
        public static (bool, string) GetSampleRate(string filePath)
        {
            string output;

            var cmd = $"-v quiet -print_format json -show_format -show_streams -print_format json {filePath}";

            Process p = new Process();
            p.StartInfo.FileName = $"{Directory.GetCurrentDirectory()}/Tools/ffmpeg/ffprobe.exe";
            p.StartInfo.Arguments = cmd;
            p.StartInfo.CreateNoWindow = true;         // 不创建新窗口    
            p.StartInfo.UseShellExecute = false;       // 不启用shell启动进程  
            p.StartInfo.RedirectStandardInput = true;  // 重定向输入    
            p.StartInfo.RedirectStandardOutput = true; // 重定向标准输出    
            p.StartInfo.RedirectStandardError = true;  // 重定向错误输出  
            p.Start();
            p.WaitForExit();

            //正常运行结束放回代码为0
            if (p.ExitCode != 0)
            {
                output = p.StandardError.ReadToEnd();
                output = output.ToString().Replace(System.Environment.NewLine, string.Empty);
                output = output.ToString().Replace("\n", string.Empty);

                return (false, output);
            }
            else
            {
                output = p.StandardOutput.ReadToEnd();
                return (true, output);
            }
        }

        /// <summary>
        /// FFmpeg 操作方法
        /// </summary>
        /// <param name="p"></param>
        /// <param name="Arguments"></param>
        /// <param name="outputDestinationFolder"></param>
        /// <param name="logTag"></param>
        /// <param name="isEnd"></param>
        /// <returns></returns>
        public static bool FfmpegExecute(string inputFilePath, string outputFilePath)
        {
            var p = new Process();
            try
            {
                var cmd = $" -i {inputFilePath} -map_metadata -1 -acodec pcm_s16le -ac 1 -ar 8000 {outputFilePath} -y";
                //var cmd = $"ffmpeg -i {inputFilePath} -map_metadata -1 -acodec pcm_s16le -ac 1 -ar 8000 {outputFilePath} -y ";

                p.StartInfo.FileName = @$"{Directory.GetCurrentDirectory()}\Tools\ffmpeg\ffmpeg.exe";

                p.StartInfo.Arguments = cmd;// $"-i {liveUrl} -c {recordFile}";//参数(这里就是FFMPEG的参数了)
                p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN)
                p.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中(这个一定要注意,FFMPEG的所有输出信息,都为错误输出流,用StandardOutput是捕获不到任何消息的.....mencoder就是用standardOutput来捕获的)
                p.StartInfo.CreateNoWindow = true;//不创建进程窗口
                p.ErrorDataReceived += Output("");//new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
                p.StartInfo.RedirectStandardInput = true;//把外部程序的输入重定向到当前进程
                var isStart = p.Start();//启动线程

                p.BeginErrorReadLine();//开始异步读取

                var isEnd = p.WaitForExit(14400 * 1000);//阻塞等待进程结束
                p.StandardInput.WriteLine("q");//控制ffmpeg退出录制
                return true;
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                p.Close();
                p.Dispose();
            }
        }

        private static DataReceivedEventHandler Output(string logTag)
        {
            return new DataReceivedEventHandler((sender, e) =>
            {
                Console.WriteLine($"时间：{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}，文件处理{logTag}");
                Console.WriteLine(e.Data);
            });
        }

        /// <summary>
        /// 启动一个可执行程序
        /// </summary>
        /// <param name="appPath"></param>
        /// <param name="arguments">启动参数</param>
        /// <returns></returns>
        public static bool StartExe(string appPath, string arguments = null)
        {
            using (Process p = new Process())
            {
                try
                {
                    p.StartInfo.FileName = appPath;
                    p.StartInfo.Arguments = arguments;
                    p.StartInfo.UseShellExecute = false;            //设置false只能启动一个程序
                    p.StartInfo.CreateNoWindow = false;             //显示程序窗口
                    p.Start();//启动程序执行
                    return true;
                }
                catch (Exception)
                {
                    return false;
                }
            }
        }
    }
}